import cmath
import math

import cv2
import numpy as np

from _0work_tools import cv_show
from _0work_tools import box_filter_factor
from _03fulfill import fulfill_border
from _0work_tools import img_box_operate
from _0work_tools import img_merge
from _0work_tools import img_add
"""
@Project: pythonPro1
@Name: _08my_fourier.py
@Author: linxin_liu
@Date: 2022/10/19 15:18
"""
# 像素*(-1)^(x+y)，转到中心。
# 先对每个像素进行傅里叶变换，每个结果都是复数。
# 循环遍历每个像素，分别获取实部的平方和虚部的平方的和的根号。就是傅里叶频谱。


# DFT
def dft(img):
    H, W, channel = img.shape
    # 编制DFT系数
    G = np.zeros((H, W, channel), dtype=complex)  # 用来存储结果。

    # 准备与原始图像位置对应的处理索引
    x = np.tile(np.arange(W), (H, 1))
    y = np.arange(H).repeat(W).reshape(H, -1)

    # dft
    for c in range(channel):
        for v in range(H):
            for u in range(W):
                img[v, u, c] = img[v, u, c] * ((-1) ** (u + v))  # 为使结果居中。
                G[v, u, c] = np.sum(img[..., c] * np.exp(-2j * np.pi * (x * u / W + y * v / H))) / np.sqrt(H * W)

    return G


def dft_a(img):  # 频谱
    H, W, channel = img.shape
    # 编制DFT系数
    G = np.zeros((H, W, channel), dtype=np.uint8)  # 用来存储结果。

    for c in range(channel):
        for v in range(H):
            for u in range(W):
                G[v, u, c] = math.sqrt(img[v, u, c].real * img[v, u, c].real + img[v, u, c].imag * img[v, u, c].imag)
    return G


def dft_one(img):  # 灰度图傅里叶变换。
    H, W = img.shape
    # 编制DFT系数
    G = np.zeros((H, W), dtype=complex)  # 用来存储结果。

    # 准备与原始图像位置对应的处理索引
    x = np.tile(np.arange(W), (H, 1))
    y = np.arange(H).repeat(W).reshape(H, -1)

    # dft
    for v in range(H):
        for u in range(W):
            img[v, u] = img[v, u] * ((-1) ** (u + v))  # 为使结果居中。
            G[v, u] = np.sum(img[...] * np.exp(-2j * np.pi * (x * u / W + y * v / H))) / np.sqrt(H * W)

    # 编制DFT系数
    after = np.zeros((H, W), dtype=np.uint8)  # 用来存储频率域结果。
    for v in range(H):  # 频率谱
        for u in range(W):
            after[v, u] = math.sqrt(G[v, u].real * G[v, u].real + G[v, u].imag * G[v, u].imag)
    return after


def flourier(img_ori):  # 书163页  未优化的傅里叶变换(没有把二维DFT分离)。
    img_temp = np.array([[i * 0 for j in range(len(img_ori[0]))] for i in range(len(img_ori))])
    img_temp = np.array(img_temp, dtype=np.complex_)  # 修改数据类型为复数。
    # print('img_temp')
    # print(img_temp)
    e = 2.72
    one_imag = cmath.sqrt(-1)  # 虚部 -j
    pi = 3.14  # π
    for u in range(0, len(img_temp)):  # 循环频率域。
        for v in range(0, len(img_temp[0])):
            img_ori[u][v] = img_ori[u][v]*((-1)**(u+v))  # 为使结果居中。
            counts = 0
            for x in range(0, len(img_ori)):  # 求和。
                for y in range(0, len(img_ori[0])):
                    temp = (u*x/len(img_ori) + v*y/len(img_ori[0]))
                    temp_variable = e**(one_imag*2*pi*temp)
                    counts = counts + img_ori[x][y]*temp_variable
            img_temp[u][v] = counts
    # img_temp就是离散傅里叶变换结果，每个元素是复数。
    # 每个元素的 实部的平方+虚部的平方的和 开根号就是傅里叶频谱。书169页。
    img_end = np.array([[i * 0 for j in range(len(img_ori[0]))] for i in range(len(img_ori))])
    # img_end = np.array(img_end, dtype=np.complex_)  # 修改数据类型为复数。
    for i in range(0, len(img_end)):  # 循环频率域。
        for j in range(0, len(img_end[0])):
            img_end[i][j] = math.sqrt(img_temp[i][j].real*img_temp[i][j].real + img_temp[i][j].imag*img_temp[i][j].imag)
    return np.array(img_end, dtype=np.uint8)


def flourier_dis(img):  # 二维DFT分离 第四版书209页。
    h, w = len(img), len(img[0])  # 高，宽
    e = 2.72
    pi = 3.14  # π
    one_imag = cmath.sqrt(-1)  # 虚部 -j
    res_x = np.zeros((h, w), dtype=complex)  # 用来存储结果。
    res_y = np.zeros((h, w), dtype=complex)  # 用来存储DFT结果。
    res_fre = np.zeros((h, w), dtype=np.uint8)  # 用来存储DFT的频率域结果。
    for x in range(0, h):  # 行
        for v in range(0, w):  # 列
            counts = 0
            for y in range(0, w):
                counts = counts + img[x][y]*(e**(-one_imag*2*pi*v*y/w))  # 每行对应的v
            res_x[x][v] = counts  # f(x,v)

    for u in range(0, h):  # 行
        for v in range(0, w):  # 列
            counts = 0
            for x in range(0, h):  # 行
                counts = counts + res_x[x][v]*(e**(-one_imag*2*pi*u*x/h))  # 每行对应的v
            res_y[u][v] = counts
    # res_y就是DFT结果。

    # 每个元素的 实部的平方+虚部的平方 的和 开根号就是傅里叶频谱。书169页。
    for i in range(0, h):  # 循环频率域。
        for j in range(0, w):
            res_fre[i][j] = math.sqrt(res_y[i][j].real * res_y[i][j].real + res_y[i][j].imag * res_y[i][j].imag)
    return res_fre


if __name__ == '__main__':
    img_original = cv2.imread('D:/tools/image_operation/mirror1.png', cv2.IMREAD_GRAYSCALE)
    # print(img_original)
    # img_original = np.array(img_original, dtype=np.complex_)  # 修改数据类型为复数。
    # img_temp = dft(img_original)
    img_after = flourier(img_original)
    cv_show('b', img_after, 0)
    # print(img_after)
    # img_after = np.array(img_after, dtype=np.uint8)  # 修改数据类型为复数
    # cv2.imwrite('D:/tools/image_operation/fuliye_white_1.png', img_after)

